<?php
// +----------------------------------------------------------------------
// | CSMITSM  [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2024 https://www.fastadmin.net All rights reserved.
// +----------------------------------------------------------------------
// | Author: chenshiming
// +----------------------------------------------------------------------

namespace app\admin\controller\csmitsm;

use addons\csmitsm\library\xcore\xcore\utils\XcDaoUtils;
use addons\csmitsm\library\xcore\xcore\utils\XcLangUtils;
use addons\csmitsm\library\xcore\xcore\utils\XcConfigUtils;
use addons\csmitsm\library\xcore\xcore\utils\XcRequestUtils;
use addons\csmitsm\library\xcore\xcore\utils\XcAdminTabUtils;
use addons\csmitsm\library\xcore\xcore\utils\XcDatabaseUtils;
use addons\csmitsm\library\xcore\xcore\utils\XcResponseUtils;
use addons\csmitsm\library\xcore\xcflow\utils\XcformDataUtils;
use addons\csmitsm\library\xcore\xcflow\utils\XcformFieldsUtils;
use addons\csmitsm\library\xcore\xcore\utils\XcRequestPathUtils;
use addons\csmitsm\library\xcore\xcore\utils\XcTransactionUtils;
use addons\csmitsm\library\xcore\xcore\utils\XcAdminSessionUtils;
use addons\csmitsm\library\xcore\xcflow\utils\XcflowInstanceUtils;
use addons\csmitsm\library\xcore\xcflow\utils\XcflowGraphDataUtils;
use addons\csmitsm\library\xcore\xcflow\base\XcformADataCrudBackend;

/**
 * 流程实例
 *
 * @icon fa fa-circle-o
 */
class Xcmyflowinstance extends XcformADataCrudBackend
{

    protected $model = null;


    public function _initialize()
    {
        parent::_initialize();
        $this->assign("statusList", ['normal' => __('Normal'), 'hidden' => __('Hidden')]);
        $this->model = new \app\admin\model\csmitsm\XcflowInstance();
        $this->xcformDao = new \app\admin\model\csmitsm\Xcflow();

        XcLangUtils::loadAdminlang("xcflow_instance");

        // csmitsm:设置页面tabs
        $xc_tabid = XcRequestUtils::param("id");
        XcAdminTabUtils::append_control_initialize('xcmyflowinstance_process', $xc_tabid, __CLASS__, $this->view);
    }

    public function allflows()
    {
        $groups = XcDaoUtils::getListBySql(new \app\admin\model\csmitsm\XcflowGroup(), []);
        $flows = XcDaoUtils::getListBySql(new \app\admin\model\csmitsm\Xcflow(), [["xcformtype", "=", "flow"]]);

        $this->view->assign("groups", $groups);
        $this->view->assign("flows", $flows);

        return $this->view->fetch();
    }

    public function index()
    {
        $this->request->filter(['strip_tags', 'trim']);
        if (false === $this->request->isAjax()) {
            $open_xcflowinstance_id = XcRequestUtils::get("open_xcflowinstance_id");
            $this->assignconfig("open_xcflowinstance_id", $open_xcflowinstance_id);
            return $this->view->fetch();
        }
    }
    public function index_daiban()
    {
        $sessionAdminid = XcAdminSessionUtils::getUserId();
        $sessionAdminGroupids = XcAdminSessionUtils::getAuthGroupIds();
        [$where, $sort, $order, $offset, $limit] = $this->buildparams();
        $list = $this->model
            ->where($where)
            ->where(function ($query) use ($sessionAdminid, $sessionAdminGroupids) {
                $query->where("xcflow_toaudit_admin_id", "=", $sessionAdminid)
                    ->whereOr("xcflow_toaudit_role_id", "in", $sessionAdminGroupids);
            })
            ->where('status', 'in', ['normal', 'draft'])
            ->order('weigh', 'desc')
            ->paginate($limit);
        $this->_appendListProperty($list);

        $result = ['total' => $list->total(), 'rows' => $list->items()];
        return json($result);
    }
    public function index_mycreate()
    {
        $sessionAdminid = XcAdminSessionUtils::getUserId();
        [$where, $sort, $order, $offset, $limit] = $this->buildparams();
        $list = $this->model
            ->where($where)
            ->where("xcflow_initiator_user_id", "=", $sessionAdminid)
            ->where('status', 'in', ['normal', 'draft'])
            ->order('weigh', 'desc')
            ->paginate($limit);

        $this->_appendListProperty($list);

        $result = ['total' => $list->total(), 'rows' => $list->items()];
        return json($result);
    }
    public function index_myaudit()
    {
        $sessionAdminid = XcAdminSessionUtils::getUserId();
        [$where, $sort, $order, $offset, $limit] = $this->buildparams();
        $list = $this->model
            ->where($where)
            ->where('id', 'in', function ($query) use ($sessionAdminid) {
                $query->table(XcDatabaseUtils::appendTablePrefix('csmitsm_xcflow_instancetrace'))
                    ->where('status', '=', 'normal')
                    ->where('trace_admin_id', '=', $sessionAdminid)
                    ->field('xcflow_instance_id');
            })
            ->where('status', 'in', ['normal', 'draft'])
            ->order('weigh', 'desc')
            ->paginate($limit);

        $this->_appendListProperty($list);

        $result = ['total' => $list->total(), 'rows' => $list->items()];
        return json($result);
    }

    private function _appendListProperty(&$list)
    {
        XcDaoUtils::bindDbListColumn($list, "xcflow_toaudit_admin_id", new \app\admin\model\Admin(), "xcflow_toaudit_admin", ["nickname"]);
        XcDaoUtils::bindDbListColumn($list, "xcflow_toaudit_role_id", new \app\admin\model\AuthGroup(), "xcflow_toaudit_role", ["name"]);

        foreach ($list as &$item) {
            $item['xcflow_toaudit_displayname'] = ($item['xcflow_toaudit_type'] == 'role') ? $item['xcflow_toaudit_role_name'] : $item['xcflow_toaudit_admin_nickname'];
        }
    }

    protected function _createOrUpdateXcformPage($xcformData)
    {
        $id = XcRequestUtils::get("id");
        $xcform_id = XcRequestUtils::get('xcform_id', true);

        $flowinstance = null;
        $xcflowinstancetraces = [];
        if (!empty($id)) {
            $flowinstance = XcDaoUtils::getRowBySql($this->model, [
                ['xcflow_flowdata_id', '=', $xcformData['id']],
                ['xcflow_id', '=', $xcform_id]
            ]);
            if ($flowinstance) {
                $xcflowinstancetraces = XcDaoUtils::getListBySql(new \app\admin\model\csmitsm\XcflowInstancetrace(), [
                    ["xcflow_instance_id", "=", $flowinstance['id']]
                ], null, ['id desc']);
            }
        }

        $hasSaveOrSubmitBtn = false;
        if ($xcformData == null) {
            $hasSaveOrSubmitBtn = true;
        } else if ($xcformData['admin_id'] == XcAdminSessionUtils::getUserId()) {
            $hasSaveOrSubmitBtn = true;
        }

        $this->assignconfig("flowinstance", $flowinstance);
        $this->assignconfig("xcflowinstancetraces", $xcflowinstancetraces);
        $this->assignconfig("hasSaveOrSubmitBtn", $hasSaveOrSubmitBtn);

        return true;
    }


    protected function _createOrUpdateXcformSubmitAjax($xcformdata)
    {
        $id = $xcformdata['id'];
        $xcform_id = XcRequestUtils::post("xcform_id");
        XcflowInstanceUtils::initRouter($xcform_id, $id, $xcformdata);

        return true;
    }

    // for my xcflow_instance page
    public function showXcflowPage()
    {
        $id = XcRequestUtils::get(["id", "ids"], true);
        $xcflowinstance = XcDaoUtils::getRowById(new \app\admin\model\csmitsm\XcflowInstance(), $id);
        XcResponseUtils::redirect("showXcformPage?xcform_id={$xcflowinstance->xcflow_id}&id={$xcflowinstance->xcflow_flowdata_id}");
    }

    // draft or xcflowInstance==null or beginFstatus -> createOrUpdateXcformPage
    public function showXcformPage()
    {
        $id = XcRequestUtils::get("id", true);
        $xcform_id = XcRequestUtils::get('xcform_id', true);

        $xcflowInstance = XcDaoUtils::getRowBySql(new \app\admin\model\csmitsm\XcflowInstance(), [
            ['xcflow_id', '=', $xcform_id],
            ['xcflow_flowdata_id', '=', $id]
        ]);

        // draft flow
        if ($xcflowInstance == null) {
            XcResponseUtils::redirect("createOrUpdateXcformPage?xcform_id={$xcform_id}&id={$id}");
            return;
        }
        //begin status
        if ($xcflowInstance && $xcflowInstance->status = 'normal') {
            $instance = XcflowGraphDataUtils::createInstance($xcform_id);
            $fstatus = $instance->getBeginStatus();
            if (empty($xcflowInstance->xcflow_fstatuscode) || $xcflowInstance->xcflow_fstatuscode == $fstatus['code']) {
                XcResponseUtils::redirect("createOrUpdateXcformPage?xcform_id={$xcform_id}&id={$id}");
                return;
            }
        }

        return parent::showXcformPage();
    }


    protected function _showXcformPage($xcformData)
    {
        $sessionAdminid = XcAdminSessionUtils::getUserId();
        $xcform_id = XcRequestUtils::get('xcform_id', true);

        $flowinstance = XcDaoUtils::getRowBySql($this->model, [
            ['xcflow_flowdata_id', '=', $xcformData['id']],
            ['xcflow_id', '=', $xcform_id]
        ]);

        $xcflowinstancetraces = XcDaoUtils::getListBySql(new \app\admin\model\csmitsm\XcflowInstancetrace(), [
            ["xcflow_instance_id", "=", $flowinstance['id']]
        ], null, ['id desc']);

        // hidden  passBtn&rejectBtn while end_status
        $hasFlowButton = ($flowinstance->xcflow_fstatuscode == 'F999') ? false : true;

        // xcflow_toaudit_type & xcflow_toaudit_admin_id & xcflow_toaudit_role_id
        if ($hasFlowButton === true) {
            switch ($flowinstance->xcflow_toaudit_type) {
                case "admin":
                    if ($flowinstance->xcflow_toaudit_admin_id == $sessionAdminid) {
                        $hasFlowButton = true;
                    } else {
                        $hasFlowButton = false;
                    }
                    break;
                case "role":
                    $authgroupIds = XcAdminSessionUtils::getAuthGroupIds();
                    if (in_array($flowinstance->xcflow_toaudit_role_id, $authgroupIds)) {
                        $hasFlowButton = true;
                    } else {
                        $hasFlowButton = false;
                    }
                    break;
                default:
                    $hasFlowButton = false;
            }
        }

        $logic = null;
        $fstatus = null;
        if (true) {
            $instance = XcflowGraphDataUtils::createInstance($xcform_id);
            $logic = $instance->getLogicByStatusCode($flowinstance['xcflow_fstatuscode'], "all");
            if ($logic) {
                $fstatus = $instance->getStatusById($logic['pass_fstatus_id']);
            }
        }

        $this->assignconfig("logicObj", $logic);
        $this->assignconfig("fstatusObj", $fstatus);
        $this->assignconfig("hasFlowButton", $hasFlowButton);
        $this->assignconfig("flowinstance", $flowinstance);
        $this->assignconfig("xcflowinstancetraces", $xcflowinstancetraces);

        return true;
    }

    public function submitPassFlowAjax()
    {
        $id = XcRequestUtils::get("id");
        $xcform_id = XcRequestUtils::get("xcform_id");
        $postFlowdata = XcRequestUtils::post('row/a', false, []);
        $tracecontent = XcRequestUtils::post("tracecontent", true);

        $flowinstance = XcflowInstanceUtils::getXcflowinstance($xcform_id, $id);

        XcTransactionUtils::service(function () use ($flowinstance, $postFlowdata, $tracecontent) {
            XcflowInstanceUtils::passRouter($flowinstance, $postFlowdata, $tracecontent, "审核通过");
        });


        $this->success("操作成功");
    }
    public function submitRejectFlowAjax()
    {
        $id = XcRequestUtils::get("id");
        $xcform_id = XcRequestUtils::get("xcform_id");
        $tracecontent = XcRequestUtils::post("tracecontent", true);

        $xcform = XcDaoUtils::getRowById($this->xcformDao, $xcform_id);
        $xcfieldjsonObj = XcformFieldsUtils::getXcfieldjsonJsonObjectFromXcform($xcform);

        $xcformdata = XcformDataUtils::getPagedataByTablenameAndRowid($xcform->publishtablename, $xcfieldjsonObj, $id);

        $flowinstance = XcflowInstanceUtils::getXcflowinstance($xcform_id, $id);

        XcTransactionUtils::service(function () use ($flowinstance, $xcformdata, $tracecontent) {
            XcflowInstanceUtils::rejectRouter($flowinstance, $xcformdata, $tracecontent);
        });


        $this->success("操作成功");
    }

    public function showFlowPageGraph()
    {
        $id = XcRequestUtils::get("id", true);

        $addoncode = XcConfigUtils::getAddonCode();
        // $xcbaseurl = XcConfigUtils::config("xcbaseurl") . "/addons/{$addoncode}/xc_flow/";
        $xcbaseurl = XcRequestPathUtils::urlAddons("/xc_flow/");

        $param = ["xcbaseurl" => $xcbaseurl];

        $url = XcRequestUtils::appendUrlParams("/public/assets/addons/{$addoncode}/h5/xcflow/xcflow", $param);
        $xdebugSrc = XcRequestUtils::appendUrlParams("http://localhost:8080/#/?xcform_id=" . $id, $param);

        return $this->fetchIframePage($url, $xdebugSrc);
    }

    protected function _getShowXcformPageShowXcfieldjsonObj($xcform_id, &$xcformFields, $xcformdata)
    {
        $fstatuscode = null;
        if ($xcformdata != null) {
            $flowinstance = XcflowInstanceUtils::getXcflowinstance($xcform_id, $xcformdata['id']);
            if (isset($flowinstance['xcflow_fstatuscode'])) {
                $fstatuscode = $flowinstance['xcflow_fstatuscode'];
            }
        }

        $instance = XcflowGraphDataUtils::createInstance($xcform_id);
        $beginstatus = $instance->getBeginStatus();
        $logic = $instance->getLogicByStatusCode($fstatuscode, 'all');

        if ($logic != null) {
            // xcflow_page use xcflow_config
            $results = [];
            foreach ($xcformFields as &$field) {
                if (isset($logic['config_fields'][$field['__vModel__']])) {
                    $tt = $logic['config_fields'][$field['__vModel__']];
                    if ($tt['show'] == "Y") {
                        $results[] = $field;
                    }
                } else {
                    $results[] = $field;
                }
            }
        } else {
            // end status
            foreach ($xcformFields as &$field) {
                $results[] = $field;
            }
        }

        return $results;
    }

    protected function _getShowXcformPageEditXcfieldjsonObj($xcform_id, &$xcformFields, $xcformdata)
    {
        $fstatuscode = null;
        if ($xcformdata != null) {
            $flowinstance = XcflowInstanceUtils::getXcflowinstance($xcform_id, $xcformdata['id']);
            if (isset($flowinstance['xcflow_fstatuscode'])) {
                $fstatuscode = $flowinstance['xcflow_fstatuscode'];
            }
        }

        $instance = XcflowGraphDataUtils::createInstance($xcform_id);
        $beginstatus = $instance->getBeginStatus();
        $logic = $instance->getLogicByStatusCode($fstatuscode, 'all');

        // xcflow_page use xcflow_config
        $results = [];
        foreach ($xcformFields as &$field) {
            $isuse = false;
            if (isset($logic['config_fields'][$field['__vModel__']])) {
                $tt = $logic['config_fields'][$field['__vModel__']];
                $isuse = ($tt['edit'] == "Y") ? true : false;

                if ($logic['flowfstatus_id'] != $beginstatus['id']) {
                    $field['fieldjsonObj']['xcform_prop_required']['value'] = $tt['required'];
                }
            } else {
                $isuse = false;
            }

            if ($isuse === true) {
                $results[] = $field;
            }
        }

        return $results;
    }


    public function del($ids = null)
    {
        $id = $ids;
        $xcform_id = XcRequestUtils::get("xcform_id", true);
        $xcform = XcDaoUtils::getRowById($this->xcformDao, $xcform_id);



        $instance = XcDaoUtils::getRowBySql(new \app\admin\model\csmitsm\XcflowInstance(), [
            ["xcflow_id", "=", $xcform_id],
            ["xcflow_flowdata_id", "=", $id]
        ]);
        if ($instance) {
            $instance->save([
                'status' => "hidden"
            ]);
        }
        $this->success();
    }
}
